package j2EE.servlet;

import com.google.common.collect.Lists;
import lombok.extern.log4j.Log4j2;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Created with Intel IDEA.
 * 简单的资源池
 *
 * @Auther: gjt
 * @Date: 2024/11/30 15:45
 */
@Log4j2
public class ResourcePool {
    private ResourceFactory resourceFactory;
    private int maxObjects;
    private int curObjects;
    private boolean quit;

    // 所有的资源
    private Set outResources;

    // 等待的资源
    private List inResource;

    public ResourcePool(ResourceFactory factory, int maxObjects) {
        this.resourceFactory = factory;
        this.maxObjects = maxObjects;

        curObjects = 0;
        outResources = new HashSet(maxObjects);
        inResource = Lists.newLinkedList();
    }

    // 从池中查找资源
    public synchronized Object getResource() throws Exception {
        while (!quit) {
            // 首先查找已有的资源
            if (!inResource.isEmpty()) {
                Object o = inResource.remove(0);

                // 如果资源无效，创建一个替换者
                if (!resourceFactory.validateResource(o)) {
                    o = resourceFactory.createResource();
                    outResources.add(o);
                    return o;
                }

                // 如果为超出限制则创建一个新资源
                if (curObjects < maxObjects) {
                    Object resource = resourceFactory.createResource();
                    outResources.add(resource);
                    curObjects++;
                    return o;
                }

                // 如果没有可用资源 则等待直到一个返回
                try {
                    wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

            }
        }
        // 池被毁坏
        log.error("资源池被毁坏！");
        return null;
    }

    // 返回一个资源到池中
    public synchronized void returnResource(Object o) {
        if(!outResources.remove(o)){
            throw new RuntimeException(" 返回资源出错");
        }

        inResource.add(o);
        notify();
    }

    public synchronized void destroy(){
        quit = true;
        notifyAll();
    }
}
